package io.kiki.sba.registry.server.clientInterface.providedata;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.kiki.sba.registry.common.model.constants.ValueConstants;
import io.kiki.sba.registry.common.model.metaserver.ProvideData;
import io.kiki.sba.registry.common.model.sessionserver.GrayOpenPushSwitchRequest;
import io.kiki.sba.registry.server.clientInterface.bootstrap.Config;
import io.kiki.sba.registry.server.clientInterface.providedata.FetchGrayPushSwitchService.GrayPushSwitchStorage;
import io.kiki.sba.registry.server.shared.providedata.AbstractFetchSystemPropertyService;
import io.kiki.sba.registry.server.shared.providedata.SystemDataStorage;
import io.kiki.sba.registry.util.JsonUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class FetchGrayPushSwitchService extends AbstractFetchSystemPropertyService<GrayPushSwitchStorage> {
    private static final Logger logger = LoggerFactory.getLogger(FetchGrayPushSwitchService.class);

    @Autowired
    private Config config;

    public FetchGrayPushSwitchService() {
        super(ValueConstants.PUSH_SWITCH_GRAY_OPEN_DATA_ID, new GrayPushSwitchStorage(INIT_VERSION, Collections.emptySet()));
    }

    @Override
    protected int getSystemPropertyIntervalMillis() {
        return config.getSystemPropertyIntervalMillis();
    }

    @Override
    protected boolean doProcess(GrayPushSwitchStorage expect, ProvideData provideData) {
        if (provideData == null) {
            logger.info("fetch session gray pushSwitch null");
            return true;
        }
        final String data = ProvideData.toString(provideData);

        GrayOpenPushSwitchRequest request = new GrayOpenPushSwitchRequest();
        if (!StringUtils.isBlank(data)) {
            ObjectMapper mapper = JsonUtils.getJacksonObjectMapper();
            try {
                request = mapper.readValue(data, GrayOpenPushSwitchRequest.class);
            } catch (IOException e) {
                throw new RuntimeException(String.format("parse gray open switch failed: %s", data), e);
            }
        }
        GrayPushSwitchStorage update = new GrayPushSwitchStorage(provideData.getVersion(), request.getIps());
        if (!compareAndSet(expect, update)) {
            return false;
        }

        logger.info("fetch session gray pushSwitch={}, prev={}", request, expect.openIps);
        return true;
    }

    public Collection<String> getOpenIps() {
        return storage.get().openIps;
    }

    protected boolean canPush() {
        return CollectionUtils.isNotEmpty(storage.get().openIps);
    }


    public void setOpenIps(long version, Collection<String> openIps) {
        storage.set(new GrayPushSwitchStorage(version, openIps));
    }


    protected FetchGrayPushSwitchService setSessionServerConfig(Config config) {
        this.config = config;
        return this;
    }

    protected static class GrayPushSwitchStorage extends SystemDataStorage {
        final Set<String> openIps;

        public GrayPushSwitchStorage(long version, Collection<String> openIps) {
            super(version);
            this.openIps = openIps == null ? Collections.emptySet() : new HashSet<>(openIps);
        }
    }
}
